package com.hulk.sequence.config;


import com.hulk.sequence.builder.DbSeqBuilder;
import com.hulk.sequence.builder.RedisSeqBuilder;
import com.hulk.sequence.builder.SnowflakeSeqBuilder;

import com.hulk.sequence.config.properties.BaseSequenceProperties;
import com.hulk.sequence.config.properties.SequenceDbProperties;
import com.hulk.sequence.config.properties.SequenceRedisProperties;
import com.hulk.sequence.config.properties.SequenceSnowflakeProperties;
import com.hulk.sequence.range.impl.name.DateBizName;
import com.hulk.sequence.range.impl.name.DefaultBizName;
import com.hulk.sequence.sequence.Sequence;
import com.hulk.sequence.util.IdWorker;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import javax.sql.DataSource;



/**
 * @author hulk
 * @date 2019-05-26
 */
@Configuration
@ConditionalOnProperty(name = "enabled", prefix = BaseSequenceProperties.PREFIX, havingValue = "true")
public class SequenceAutoConfiguration {




	/**
	 * 数据库作为发号器的存储介质
	 */
	@Configuration
	@AutoConfigureAfter(DataSource.class)
	@ConditionalOnProperty(name = "name", prefix = BaseSequenceProperties.PREFIX, havingValue = "db")
	@EnableConfigurationProperties({SequenceDbProperties.class})
	public static class DbSequenceConfig {


		@Bean
		@ConditionalOnMissingBean
		public Sequence dbSequence(SequenceDbProperties  sequenceDbProperties, ObjectProvider<DataSource> dataSource) {
			return DbSeqBuilder
					.create()
					.bizName(new DefaultBizName(sequenceDbProperties.getBizName()))
					.dataSource(dataSource.getIfAvailable())
					.step(sequenceDbProperties.getStep())
					.stepStart(sequenceDbProperties.getStepStart())
					.retryTimes(sequenceDbProperties.getRetryTimes())
					.tableName(sequenceDbProperties.getTableName())
					.build();
		}
	}


	/**
	 * Redis 作为发号器的存储介质
	 */
	@Configuration
	@AutoConfigureAfter(RedisAutoConfiguration.class)
	@ConditionalOnProperty(name = "name", prefix = BaseSequenceProperties.PREFIX, havingValue = "redis")
	@EnableConfigurationProperties({SequenceRedisProperties.class})
	public static class RedisSequenceConfig {


		@Bean(value = "seqRedisTemplate")
		@ConditionalOnMissingBean
		public StringRedisTemplate seqRedisTemplate(
				RedisConnectionFactory redisConnectionFactory) {
			return new StringRedisTemplate(redisConnectionFactory);
		}


		@Bean
		@ConditionalOnMissingBean
		public Sequence redisSequence(RedisTemplate seqRedisTemplate,SequenceRedisProperties  sequenceRedisProperties) {

			return RedisSeqBuilder
					.create()
					.bizName(new DateBizName(sequenceRedisProperties.getBizName()))
					.step(sequenceRedisProperties.getStep())
					.stepStart(sequenceRedisProperties.getStepStart()+ IdWorker.getId())
					.seqRedisTemplate(seqRedisTemplate)
					.build();
		}
	}



	/**
	 * snowflak 算法作为发号器实现
	 */
	@Configuration
	@ConditionalOnProperty(name = "name", prefix = BaseSequenceProperties.PREFIX, havingValue = "snowflake")
	@EnableConfigurationProperties({SequenceSnowflakeProperties.class})
	public static class SnowflakeSequence {

		@Bean
		@ConditionalOnMissingBean
		public Sequence snowflakeSequence(SequenceSnowflakeProperties  sequenceSnowflakeProperties) {
			return SnowflakeSeqBuilder
					.create()
					.datacenterId(sequenceSnowflakeProperties.getDatacenterId())
					.build();
		}
	}


}